<script lang="ts" setup>
import type { CheckboxChangeEvent } from 'ant-design-vue/es/checkbox/interface'
import type { Exposed, OpenCallback, OpenData } from './type'
import { ENavigation01IconType } from '@/api/designer/model'
import { useUpload } from '@/hooks/useUpload'
import { useInstStore } from '@/stores'
import { iconfontCls, imageIcons } from '@/utils/constants'
import { warn } from '@/utils/helper'
import { Button, Checkbox, Input, Modal } from 'ant-design-vue'
import { ref, toValue } from 'vue'

defineOptions({
  name: 'IconSelectModal',
})
const instStore = useInstStore()
const open = ref(false)
const currentItem = ref<Nullable<OpenData>>()
const currentItemCallback = ref<Nullable<OpenCallback>>()
defineExpose<Exposed>({
  async open(_data, _callback) {
    // 图标颜色默认为主题色
    if (_data.icon.iconUseThemeColor) {
      _data.icon.iconColor = instStore.detail?.themeColor
    }
    currentItem.value = _data
    currentItemCallback.value = _callback
    open.value = true
  },
})
const uploadUrl = ref<string>()
const { uploadAction } = useUpload({
  successHandler({ url }) {
    if (currentItem.value) {
      currentItem.value.icon.icon = uploadUrl.value = url
      currentItem.value.icon.iconColor = ''
    }
  },
})
function handleCancel() {
  const callback = toValue(currentItemCallback)
  if (callback) {
    callback({
      applied: false,
      value: null,
    })
  }
  cleanUp()
}
function cleanUp() {
  open.value = false
  currentItem.value = null
  currentItemCallback.value = null
  uploadUrl.value = ''
}
function handleOk() {
  const currentValue = toValue(currentItem)
  const callback = toValue(currentItemCallback)
  if (!currentValue || !callback) {
    warn('[IconSelectModal] currentValue 或 callback 缺失')
    return handleCancel()
  }
  // 点击确定，选择了图标才算应用，否则还是算丢弃
  if (currentValue.icon.icon) {
    callback({
      applied: true,
      value: currentValue,
    })
    cleanUp()
  }
  else {
    handleCancel()
  }
}
function handleResetColor() {
  if (currentItem.value) {
    currentItem.value.icon.iconColor = instStore.detail?.themeColor
  }
}
function handleChooseIcon(icon: string) {
  if (currentItem.value) {
    currentItem.value.icon.icon = icon
  }
}
function handleUseThemeColor(ev: CheckboxChangeEvent) {
  if (ev.target.checked) {
    handleResetColor()
  }
}
</script>

<template>
  <Modal v-model:open="open" title="选择图标" :width="632" @cancel="handleCancel" @ok="handleOk">
    <div class="box-border">
      <div v-if="currentItem?.iconType === ENavigation01IconType.矢量图标" class="box-border">
        <div class="flex flex-row items-center gap-5 mb-3">
          <div class="text-second-app text-sm">
            跟随主题:
          </div>
          <div class="flex flex-row items-center gap-2">
            <Checkbox v-model:checked="currentItem.icon.iconUseThemeColor" @change="handleUseThemeColor" />
            <span class="text-sm text-second-app">(选中后图标颜色将始终跟随设计器主题色，背景颜色将设置无效！)</span>
          </div>
        </div>
        <div class="flex flex-row items-center gap-5">
          <div class="text-second-app text-sm">
            背景颜色:
          </div>
          <div class="flex flex-row items-center gap-2">
            <span class="text-second-app text-sm">色值</span>
            <div
              class="flex flex-row items-center gap-2 px-3 border border-solid border-[var(--app-color-border)] w-160px"
            >
              <div class="box-border w-4 h-4 flex-none" :style="{ backgroundColor: currentItem.icon.iconColor }" />
              <Input
                v-model:value="currentItem.icon.iconColor" :bordered="false" class="text-main-app"
                placeholder="#RRGGBB"
                :disabled="currentItem.icon.iconUseThemeColor"
              />
            </div>
            <span class="cursor-pointer text-sm text-primary-app" @click="handleResetColor">重置</span>
          </div>
        </div>
        <div class="mt-18px">
          <div class="text-second-app text-sm">
            图标库中选择:
          </div>
          <div class="flex flex-row flex-wrap gap-3 box-border mt-3">
            <!-- item for loop -->
            <div
              v-for="item of iconfontCls" :key="item" class="font-icon-item"
              :class="item === currentItem.icon.icon ? 'font-icon-item__checked' : ''" @click="handleChooseIcon(item)"
            >
              <i
                class="text-48px !leading-none iconfont" :class="item"
                :style="{ color: currentItem.icon.iconColor }"
              />
            </div>
          </div>
        </div>
      </div>
      <div v-else-if="currentItem?.iconType === ENavigation01IconType.图片图标" class="box-border">
        <div class="flex flex-row items-start gap-5">
          <div class="text-second-app text-sm">
            从素材中心选择图片:
          </div>
          <div class="box-border">
            <div class="flex flex-row items-end gap-2">
              <img v-if="uploadUrl" :src="uploadUrl" :width="64" :height="64" class="w-64px h-64px object-contain">
              <Button
                type="primary" class="flex items-center justify-center gap-1"
                @click="uploadAction"
              >
                <template #icon>
                  <i class="i-ant-design:plus-circle-outlined w-4 h-4" />
                </template>
                上传图片
              </Button>
            </div>
            <div class="text-[#999999] text-sm mt-2">
              上传建议：尺寸为1:1，png.jpg.bmp格式，不大于2M。
            </div>
          </div>
        </div>
        <div class="mt-18px">
          <div class="text-second-app text-sm">
            图标库中选择:
          </div>
          <div class="flex flex-row flex-wrap gap-3 box-border mt-3">
            <!-- item for loop -->
            <div
              v-for="item of imageIcons" :key="item" class="font-icon-item"
              :class="item === currentItem.icon.icon ? 'font-icon-item__checked' : ''" @click="handleChooseIcon(item)"
            >
              <img :src="item" :width="64" :height="64" class="w-64px h-64px object-contain block box-border">
            </div>
          </div>
        </div>
      </div>
    </div>
  </Modal>
</template>

<style lang="less" scoped>
.font-icon-item {
  width: 64px;
  height: 64px;
  background: #EEE;
  @apply flex flex-row justify-center items-center cursor-pointer box-border;

  &:hover,
  &.font-icon-item__checked {
    border: 1px solid var(--app-color-primary);
    background: #FFF;
  }
}
</style>
